home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / alias.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-13  |  57.3 KB  |  1,937 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: alias.c,v 5.34 1993/05/14 03:57:36 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.34 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1988-1992 USENET Community Trust
  8.  *             Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: alias.c,v $
  17.  * Revision 5.34  1993/05/14  03:57:36  syd
  18.  * A couple of calls to want_to() had typos. Here is the patch.
  19.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  20.  *
  21.  * Revision 5.33  1993/05/14  03:53:46  syd
  22.  * Fix wrong message being displayed and then overwritten
  23.  * for long aliases.
  24.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  25.  *
  26.  * Revision 5.32  1993/05/08  20:25:33  syd
  27.  * Add sleepmsg to control transient message delays
  28.  * From: Syd
  29.  *
  30.  * Revision 5.31  1993/05/08  17:04:15  syd
  31.  * Jan's removal of tolower in alias.c breaks help for 'I'.  This fixes
  32.  * that and makes the help messages for characters that have printable
  33.  * synonyms on the alias and options screens consistent with the help files.
  34.  * From: dwolfe@pffft.sps.mot.com (Dave Wolfe)
  35.  *
  36.  * Revision 5.30  1993/04/21  01:33:49  syd
  37.  * Use pointer arithmetic for aliases on crays
  38.  * From: Quentin Van Abbe <rxxqva@argolis.osf.rmit.OZ.AU>
  39.  *
  40.  * Revision 5.29  1993/04/12  03:15:41  syd
  41.  * These patches makes 'T' (since it was free) do a Tag and Move command in the
  42.  * index and alias page, and in the builtin pager.
  43.  * In the alias help in src/alias.c, there is a tolower done on the character
  44.  * one wants help for.  This is clearly wrong.
  45.  * From: Jan Djarv <Jan.Djarv@sa.erisoft.se>
  46.  *
  47.  * Revision 5.28  1993/04/12  03:00:57  syd
  48.  * None of i, q, x, >, and ^L are recognized by the single character help
  49.  * on the options screen.  <return> causes the options screen to scroll
  50.  * because all non-printing characters are echoed by the error message.
  51.  * Options and alias help files didn't list all commands.
  52.  * From: dwolfe@pffft.sps.mot.com (Dave Wolfe)
  53.  *
  54.  * Revision 5.27  1993/04/12  02:34:36  syd
  55.  * I have now added a parameter which controls whether want_to clears the
  56.  * line and centers the question or behaves like it did before. I also
  57.  * added a 0 at the end of the parameter list to all the other calls to
  58.  * want_to where a centered question on a clean line is not desirable.
  59.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  60.  *
  61.  * Revision 5.26  1993/04/12  01:14:11  syd
  62.  * The test in delete did not take into account for mixed case.
  63.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  64.  *
  65.  * Revision 5.25  1993/04/12  01:13:05  syd
  66.  * Move first name to lastname if lastname blank.
  67.  * this is the only real way for now.  I think that the dbz stuff, sorting,
  68.  * and other things all hope to see a lastname.
  69.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  70.  *
  71.  * Revision 5.24  1993/04/12  01:10:15  syd
  72.  * fix @aliasname sort problem
  73.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  74.  *
  75.  * Revision 5.23  1993/04/12  01:08:16  syd
  76.  * test firstname == lastname and if true zero out firstname before
  77.  * writing to the aliases.text file.  Let me check out the source.  Now if
  78.  * you try to change a SYSTEM alias it lets you know and asks to verify
  79.  * that you are going to superceed that alias.
  80.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  81.  *
  82.  * Revision 5.22  1993/02/03  16:56:59  syd
  83.  * Fix which seek is being used on DBZ file, FILE * requires fseek
  84.  * From: syd via prompt from mfvargo@netcom.com (Michael Vargo)
  85.  *
  86.  * Revision 5.21  1993/01/20  03:37:16  syd
  87.  * Nits and typos in the NLS messages and corresponding default messages.
  88.  * From: dwolfe@pffft.sps.mot.com (Dave Wolfe)
  89.  *
  90.  * Revision 5.20  1993/01/19  04:52:19  syd
  91.  *     add c)hange alias command to alias helpfile
  92.  *     if a deleted alias is changed, undelete it.  Also added the 'N'
  93.  * flag to changed aliases to help remind the user.  Documented it.
  94.  * Note:  if they mark the alias for deletion AFTER making the change it
  95.  * WILL be deleted. (and marked accordingly)
  96.  *     modified alias mode title string to indicate when a resync was
  97.  * needed.
  98.  *     allow editing alias file when none exist.
  99.  *     Now aliases are check for illegal characters (and WS) and
  100.  * addresses are check for illegal WS when they are being entered.  If
  101.  * anything illegal is found and message is printed and they keep entering
  102.  * the item until they get it right.
  103.  *     I fixed a couple of places where int should be long to match
  104.  * the declared type of alias_rec.length
  105.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  106.  *
  107.  * Revision 5.19  1992/12/24  21:42:01  syd
  108.  * Fix messages and nls messages to match.  Plus use want_to
  109.  * where appropriate.
  110.  * From: Syd, via prompting from Jan Djarv <Jan.Djarv@sa.erisoft.se>
  111.  *
  112.  * Revision 5.18  1992/12/20  05:15:58  syd
  113.  * Add a c)hange alias, -u and -t options to listalias to list only user
  114.  * and only system aliases respectively.
  115.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  116.  *
  117.  * Revision 5.17  1992/12/13  17:59:18  syd
  118.  * Please write on the blackboard 500 times `NULL != 0.'
  119.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  120.  *
  121.  * Revision 5.16  1992/12/11  02:09:06  syd
  122.  * Fix where the user creates a first new alias, then deletes it, the
  123.  * alias stays on screen, but the file really will be empty if it was the
  124.  * last alias, so the retry to delete gives 'cannot open ...file' messages
  125.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  126.  *
  127.  * Revision 5.15  1992/12/11  01:58:22  syd
  128.  * Anytime elm wants to re-run newalias, selected is set to 0.
  129.  * (removing any limit in effect)
  130.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  131.  *
  132.  * Revision 5.14  1992/12/11  01:45:04  syd
  133.  * remove sys/types.h include, it is now included by defs.h
  134.  * and this routine includes defs.h or indirectly includes defs.h
  135.  * From: Syd
  136.  *
  137.  * Revision 5.13  1992/12/07  03:02:03  syd
  138.  * On machines with 64 bit pointers (and 64 bit longs) using int
  139.  * for newmax causes pointer truncation.
  140.  * From: Jim Brown
  141.  *
  142.  * Revision 5.12  1992/11/26  00:46:50  syd
  143.  * Fix how errno is used so err is inited and used instead
  144.  * as errno gets overwritten by print system call
  145.  * From: Syd
  146.  *
  147.  * Revision 5.11  1992/11/15  01:24:34  syd
  148.  * The situation is that the .elm/aliases file is missing, but
  149.  * .elm/aliases.dir and .elm/aliases.pag exist (isn't serendipity
  150.  * wonderful?).  The ndbz functions tolerate this and just put a NULL
  151.  * pointer in the db structure for the data file FILE pointer.  However,
  152.  * get_one_alias() in listalias and elm doesn't account for the db_open()
  153.  * succeeding but the dbz_basef field being NULL, so it passes the NULL
  154.  * pointer to fread().  Detect null and return 0
  155.  * From: dwolfe@pffft.sps.mot.com (Dave Wolfe)
  156.  *
  157.  * Revision 5.10  1992/11/15  01:15:28  syd
  158.  * The alias message_count isn't set to zero if the last alias has
  159.  * been deleted from the alias table. As no aliases are reread from
  160.  * the aliases database the message_count is left as it was before.
  161.  *
  162.  * Fixed that the function do_newalias() sometimes returns without freeing
  163.  * the buffer allocated before. The patch adds these free calls.
  164.  *
  165.  * When you erroneously type a number in your folder elm asks you for
  166.  * a new current message number. But now if you erase this one number
  167.  * and leave the string empty elm will set the new current message to
  168.  * the second message on our sun4! The patch adds a check for an empty
  169.  * string and returns the current number if no number was entered.
  170.  * From: vogt@isa.de (Gerald Vogt)
  171.  *
  172.  * Revision 5.9  1992/10/24  13:35:39  syd
  173.  * changes found by using codecenter on Elm 2.4.3
  174.  * From: Graham Hudspith <gwh@inmos.co.uk>
  175.  *
  176.  * Revision 5.8  1992/10/19  16:58:18  syd
  177.  * more on the update of compiler warnings
  178.  * From: Syd
  179.  *
  180.  * Revision 5.7  1992/10/19  16:50:41  syd
  181.  * Fix a couple more compiler gripes from SYSVR4
  182.  * From: Tom Moore <tmoore@wnas.DaytonOH.NCR.COM>
  183.  *
  184.  * Revision 5.6  1992/10/17  22:47:09  syd
  185.  * adds the function bytemap() and the macros MAPIN and MAPOUT from the file
  186.  * lib/ndbz.c in the file src/alias.c.
  187.  *
  188.  * prevent elm from exiting when resyncing the empty incoming mailbox.
  189.  * From: vogt@isa.de (Gerald Vogt)
  190.  *
  191.  * Revision 5.5  1992/10/11  01:46:35  syd
  192.  * change dbm name to dbz to avoid conflicts with partial call
  193.  * ins from shared librarys, and from mixing code with yp code.
  194.  * From: Syd via prompt from Jess Anderson
  195.  *
  196.  * Revision 5.4  1992/10/11  01:21:17  syd
  197.  * 1. If firstname && lastname is null then copy aliasname into the
  198.  * personal name field (inside the ()'s) when creating an alias
  199.  * from the menu using the 'n' command.
  200.  *
  201.  * 2. Now if for some reason and alias has a null personal name field
  202.  * (the person hand edited aliases.text) the blank () is not printed
  203.  * as part of the address.  This actually cured another problem, where
  204.  * the To: field on the screen (when you hit 'm' on the alias menu)
  205.  * used to be blank, now the address shows up....
  206.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  207.  *
  208.  * Revision 5.3  1992/10/11  01:07:52  syd
  209.  * get_return() assumes that message_count reflects the number of
  210.  * messages in the current folder, but the message_count it's seeing
  211.  * from the alias subsystem is actually the *alias* count.
  212.  * toggle the main state before and after calling get_return().
  213.  * From: cliff@sfn.ORG (R. Cliff Young)
  214.  *
  215.  * Revision 5.2  1992/10/11  00:59:39  syd
  216.  * Fix some compiler warnings that I receive compiling Elm on my SVR4
  217.  * machine.
  218.  * From: Tom Moore <tmoore@fievel.DaytonOH.NCR.COM>
  219.  *
  220.  * Revision 5.1  1992/10/03  22:58:40  syd
  221.  * Initial checkin as of 2.4 Release at PL0
  222.  *
  223.  *
  224.  ******************************************************************************/
  225.  
  226. /** This file contains alias stuff
  227.  
  228. **/
  229.  
  230. #include "headers.h"
  231. #include "s_elm.h"
  232. #include <errno.h>
  233. #include <ctype.h>
  234. #include <sys/stat.h>
  235. #include "s_aliases.h"
  236. #include "ndbz.h"
  237.  
  238. #ifdef BSD
  239. #undef        tolower
  240. #endif
  241.  
  242. #define    ECHOIT    1     /* echo on for prompting */
  243.  
  244. /*
  245.  * A simple macro to make it easier to remember how to do a simple
  246.  * resync and not screw up whether or not to prompt on deletions.
  247.  */
  248.  
  249. #define resync_aliases(newaliases)    delete_aliases(newaliases,TRUE)
  250.  
  251. extern char *alias_type(), *get_alias_address();
  252. char *error_description(), *get_parens();
  253. void get_realnames();
  254. void install_aliases();
  255.  
  256. int  is_system=0;        /* system file updating?     */
  257.  
  258. extern int errno;
  259.  
  260. int current_mail_message;
  261. int num_duplicates;
  262. DBZ *system_hash = NULL, *user_hash = NULL;
  263. char *a_rev_alias_pad, *a_rev_alias_abr, *a_rev_alias_name,
  264.     *a_rev_full_pad, *a_full_abr, *a_rev_full_name,
  265.     *a_rev_text_pad, *a_text_abr, *a_rev_text_file,
  266.     *a_alias_pad, *a_alias_abr, *a_alias_name,
  267.     *a_full_pad, *a_full_name,
  268.     *a_text_pad, *a_text_file,
  269.     *a_group_name, *a_person_name, *a_system_flag;
  270.     
  271.  
  272. open_alias_files(are_in_aliases)
  273. int are_in_aliases;
  274. {
  275.     static int first_time = TRUE;
  276. /*
  277.  *    Close and re-open the system and user alias files, if present,
  278.  *    and if they have changed since last we opened them.
  279.  *
  280.  *    Also, parse the data files into memory if needed
  281.  */
  282.     if (first_time) {
  283.         a_group_name = catgets(elm_msg_cat, AliasesSet, AliasesGroup,
  284.         " Group");
  285.         a_person_name = catgets(elm_msg_cat, AliasesSet, AliasesPerson,
  286.         "Person");
  287.         a_system_flag = catgets(elm_msg_cat, AliasesSet, AliasesSystemFlag,
  288.         "(S)");
  289.         a_rev_alias_pad = catgets(elm_msg_cat, AliasesSet, AliasesRevAliasPad,
  290.         "Reverse Alias Name      ");
  291.         a_rev_alias_abr = catgets(elm_msg_cat, AliasesSet, AliasesRevAliasAbr,
  292.         "Reverse-Alias");
  293.         a_rev_alias_name = catgets(elm_msg_cat, AliasesSet, AliasesRevAliasName,
  294.         "Reverse Alias Name");
  295.         a_rev_full_pad = catgets(elm_msg_cat, AliasesSet, AliasesRevFullPad,
  296.         "Reverse Full (Real) Name");
  297.         a_full_abr = catgets(elm_msg_cat, AliasesSet, AliasesRevFullAbr,
  298.         "Reverse-Name");
  299.         a_rev_full_name = catgets(elm_msg_cat, AliasesSet, AliasesRevFullName,
  300.         "Reverse Full (Real) Name");
  301.         a_rev_text_pad = catgets(elm_msg_cat, AliasesSet, AliasesRevTextPad,
  302.         "Reverse Text File       ");
  303.         a_text_abr = catgets(elm_msg_cat, AliasesSet, AliasesRevTextAbr,
  304.         "Reverse-Text");
  305.         a_rev_text_file = catgets(elm_msg_cat, AliasesSet, AliasesRevTextFile,
  306.         "Reverse Text File");
  307.         a_alias_pad = catgets(elm_msg_cat, AliasesSet, AliasesAliasPad,
  308.         "Alias Name              ");
  309.         a_alias_abr = catgets(elm_msg_cat, AliasesSet, AliasesAliasAbr,
  310.         "Alias");
  311.         a_alias_name = catgets(elm_msg_cat, AliasesSet, AliasesAliasName,
  312.         "Alias Name");
  313.         a_full_pad = catgets(elm_msg_cat, AliasesSet, AliasesFullPad,
  314.         "Full (Real) Name        ");
  315.         a_full_abr = catgets(elm_msg_cat, AliasesSet, AliasesFullAbr,
  316.         "Name");
  317.         a_full_name = catgets(elm_msg_cat, AliasesSet, AliasesFullName,
  318.         "Full (Real) Name");
  319.         a_text_pad = catgets(elm_msg_cat, AliasesSet, AliasesTextPad,
  320.         "Text File               ");
  321.         a_text_abr = catgets(elm_msg_cat, AliasesSet, AliasesTextAbr,
  322.         "Text");
  323.         a_text_file = catgets(elm_msg_cat, AliasesSet, AliasesTextFile,
  324.         "Text File");
  325.         first_time = FALSE;
  326.     }
  327.  
  328.     if(open_system_aliases() | open_user_aliases()) {
  329.         dprint(5, (debugfile,
  330.               "Reading alias data files...\n"));
  331.         get_aliases(are_in_aliases);
  332.     }
  333. }
  334.  
  335. int
  336. open_system_aliases()
  337. {
  338. /*
  339.  *    Open the system alias file, if present,
  340.  *    and if it has changed since last we read it.
  341.  *
  342.  *    Return 0 if hash file wasn't opened, otherwise 1
  343.  */
  344.  
  345.     struct stat hst;
  346.     static time_t system_ctime = 0, system_mtime = 0;
  347.  
  348.     /* If file hasn't changed, don't bother re-opening. */
  349.  
  350.     if (stat(system_data_file, &hst) == 0) {    /* File exists */
  351.         if (hst.st_ctime == system_ctime &&
  352.             hst.st_mtime == system_mtime) {        /* No changes */
  353.             return(0);
  354.         }
  355.  
  356.        /*
  357.         * Re-open system hash table.  If we can't, just return.
  358.         */
  359.  
  360.         if (system_hash != NULL)
  361.             dbz_close(system_hash);
  362.  
  363.         if ((system_hash = dbz_open(system_data_file, O_RDONLY, 0)) == NULL)
  364.             return(0);
  365.  
  366.         /* Remember hash file times. */
  367.  
  368.         system_ctime = hst.st_ctime;
  369.         system_mtime = hst.st_mtime;
  370.  
  371.             return(1);
  372.     }
  373.     else {                    /* File does not exist */
  374.         if (system_ctime == 0 && system_mtime == 0) {
  375.             return(0);            /* File never existed */
  376.         }
  377.         else {            /* Once existed, better re-read */
  378.  
  379.            /*
  380.             * Since we no longer exist, we pretend we never existed.
  381.             */
  382.  
  383.             system_ctime = 0;
  384.             system_mtime = 0;
  385.  
  386.             return(1);
  387.         }
  388.     }
  389.  
  390. }
  391.  
  392. int
  393. open_user_aliases()
  394. {
  395. /*
  396.  *    Open the user alias file, if present,
  397.  *    and if it has changed since last we read it.
  398.  *
  399.  *    Return 0 if hash file wasn't opened, otherwise 1
  400.  */
  401.  
  402.     struct stat hst;
  403.     char fname[SLEN];
  404.     static time_t user_ctime = 0, user_mtime = 0;
  405.  
  406.     /* If hash file hasn't changed, don't bother re-reading. */
  407.  
  408.     sprintf(fname, "%s/%s", home, ALIAS_DATA);
  409.  
  410.     if (stat(fname, &hst) == 0) {            /* File exists */
  411.         if (hst.st_ctime == user_ctime &&
  412.             hst.st_mtime == user_mtime) {        /* No changes */
  413.             return(0);
  414.         }
  415.  
  416.        /*
  417.         * Open user hash table.  If we can't, just return.
  418.         */
  419.  
  420.         if (user_hash != NULL)
  421.             dbz_close(user_hash);
  422.  
  423.         if ((user_hash = dbz_open(fname, O_RDONLY, 0)) == NULL)
  424.             return(0);
  425.  
  426.         /* Remember hash file times. */
  427.  
  428.         user_ctime = hst.st_ctime;
  429.         user_mtime = hst.st_mtime;
  430.  
  431.             return(1);
  432.     }
  433.     else {                    /* File does not exist */
  434.         if (user_ctime == 0 && user_mtime == 0) {
  435.             return(0);            /* File never existed */
  436.         }
  437.         else {            /* Once existed, better re-read */
  438.  
  439.            /*
  440.             * Since we no longer exist, we pretend we never existed.
  441.             */
  442.  
  443.             user_ctime = 0;
  444.             user_mtime = 0;
  445.  
  446.             return(1);
  447.         }
  448.     }
  449.  
  450. }
  451.  
  452. int
  453. add_alias(replace, to_replace)
  454. int replace, to_replace;
  455. {
  456. /*
  457.  *    Add an alias to the user alias text file.  If there
  458.  *    are aliases tagged, the user is asked if he wants to
  459.  *    create a group alias from the tagged files.
  460.  *
  461.  *    Return zero if alias not added in actuality.
  462.  *
  463.  *    If replace == FALSE, then we will ask for the new
  464.  *    aliasname.
  465.  *
  466.  *    If replace == TRUE, then we are replacing the alias
  467.  *    denoted by to_replace.
  468.  *
  469.  *    Note that even if replace == FALSE, if the user types
  470.  *    in the name of a current alias then we can still do
  471.  *    a replacement.
  472.  */
  473.  
  474.     int i, leftoff, tagged = 0;
  475.  
  476.     char aliasname[SLEN], firstname[SLEN], lastname[SLEN];
  477.     char address1[LONG_STRING], buffer[SLEN];
  478.     char comment[LONG_STRING], ch = *def_ans_no;
  479.     char *ch_ptr;
  480.  
  481. /*
  482.  *    See if there are any tagged aliases.
  483.  */
  484.     for (i=0; i < message_count; i++) {
  485.         if (ison(aliases[i]->status, TAGGED)) {
  486.         if (tagged == 0) leftoff = i;
  487.             tagged++;
  488.         }
  489.     }
  490.  
  491.     if (tagged == 1) {
  492.      /*
  493.       * There is only on alias tagged.  Ask the question
  494.       * but the default response is NO.
  495.       */
  496.         PutLine0(LINES-2,0, catgets(elm_msg_cat,
  497.                 AliasesSet, AliasesOneTagged,
  498.                 "There is 1 alias tagged..."));
  499.         CleartoEOLN();
  500.         MCsprintf(buffer, catgets(elm_msg_cat,
  501.                 AliasesSet, AliasesCreateGroup,
  502.                 "Create group alias? (%c/%c) "),
  503.             *def_ans_yes, *def_ans_no);
  504.         ch = want_to(buffer, *def_ans_no, LINES-3, 0);
  505.     }
  506.     else if (tagged > 1) {
  507.      /*
  508.       * If multiple tagged aliases then we assume the user
  509.       * wants to create a group alias.  The default response
  510.       * is YES.
  511.       */
  512.         PutLine1(LINES-2,0, catgets(elm_msg_cat,
  513.                 AliasesSet, AliasesManyTagged,
  514.                 "There are %d aliases tagged..."), tagged);
  515.         CleartoEOLN();
  516.         MCsprintf(buffer, catgets(elm_msg_cat,
  517.                 AliasesSet, AliasesCreateGroup,
  518.                 "Create group alias? (%c/%c) "),
  519.             *def_ans_yes, *def_ans_no);
  520.         ch = want_to(buffer, *def_ans_yes, LINES-3, 0);
  521.     }
  522.  
  523. /*
  524.  *    Create the group alias address.  This is only done
  525.  *    if one of the above want_to() questions were
  526.  *    answered YES (and thus there *were* tagged messages
  527.  *    and the user responded correctly).
  528.  */
  529.     if (ch == *def_ans_yes) {
  530.         strcpy(address1, aliases[leftoff]->alias);
  531.         for (i=leftoff+1; i < message_count; i++) {
  532.             if (ison(aliases[i]->status, TAGGED)) {
  533.                 strcat(address1, ",");
  534.                 strcat(address1, aliases[i]->alias);
  535.             }
  536.         }
  537.     }
  538.     else {
  539.         tagged = 0;
  540.     }
  541.  
  542. /*
  543.  *    Only ask for an aliasname if we are NOT replacing the
  544.  *    current alias.
  545.  */
  546.     if (replace) {
  547.         strcpy(aliasname, aliases[to_replace]->alias);
  548.     /*
  549.      *  First, see if what we are replacing is a SYSTEM
  550.      *  alias.  If so, we need to ask a question.
  551.      */
  552.         if(aliases[to_replace]->type & SYSTEM) {
  553.             dprint(3, (debugfile, 
  554.                 "Aliasname [%s] is SYSTEM in add_alias\n", aliasname));
  555.         /*
  556.          *  If they don't want to superceed the SYSTEM alias then
  557.          *  just return.
  558.          */
  559.             if( ! superceed_system(to_replace, buffer)) {
  560.                 ClearLine(LINES-2);
  561.                 return(0);
  562.             }
  563.         }
  564.     }
  565.     else {
  566.         strcpy(buffer, catgets(elm_msg_cat,
  567.                 AliasesSet, AliasesEnterAliasName, "Enter alias name: "));
  568.         PutLine0(LINES-2,0, buffer);
  569.         CleartoEOLN();
  570.         *aliasname = '\0';
  571.         if ((replace = get_aliasname(aliasname, buffer, &to_replace)) < 0) {
  572.             dprint(3, (debugfile, 
  573.                 "Aliasname [%s] was rejected in add_alias\n", aliasname));
  574.             ClearLine(LINES-2);
  575.             return(0);
  576.         }
  577.     }
  578.  
  579. /*
  580.  *    If we are replacing an existing alias, we will assume that
  581.  *    they might want to be just editing most of what is already
  582.  *    there.  So we copy some defaults from the existing alias.
  583.  */
  584.     if (replace) {
  585.         strcpy(lastname, aliases[to_replace]->last_name);
  586.         strcpy(firstname, aliases[to_replace]->name);
  587.         ch_ptr = strstr(firstname, lastname);
  588.         *(ch_ptr-1) = '\0';
  589.         strcpy(comment, aliases[to_replace]->comment);
  590.     }
  591.     else {
  592.         *lastname = '\0';
  593.         *firstname = '\0';
  594.         *comment = '\0';
  595.     }
  596.     get_realnames(aliasname, firstname, lastname, comment, buffer);
  597.  
  598. /*
  599.  *    Since there are no tagged aliases, we must ask for an
  600.  *    address.  If we are replacing, a default address is
  601.  *    presented.
  602.  */
  603.     if (tagged == 0) {
  604.         sprintf(buffer, catgets(elm_msg_cat,
  605.                 AliasesSet, AliasesEnterAddress,
  606.                 "Enter address for %s: "), aliasname);
  607.         PutLine0(LINES-2,0, buffer);
  608.         CleartoEOLN();
  609.         if (replace) {
  610.             strcpy(address1, aliases[to_replace]->address);
  611.         }
  612.         else {
  613.             *address1 = '\0';
  614.         }
  615.         do {
  616.             optionally_enter(address1, LINES-2, strlen(buffer),
  617.                              FALSE, FALSE);
  618.             Raw(ON);
  619.             if (strlen(address1) == 0) {
  620.                 error(catgets(elm_msg_cat, AliasesSet, AliasesNoAddressSpec,
  621.                         "No address specified!"));
  622.                 return(0);
  623.             }
  624.         } while (check_address(address1) == -1);
  625.  
  626.         clear_error();            /* Just in case */
  627.     }
  628.  
  629.     if(ask_accept(aliasname, firstname, lastname, comment, address1,
  630.             buffer, replace, to_replace)) {
  631.      /*
  632.       * We can only clear the tags after we know that the
  633.       * alias was added.  This allows the user to back out
  634.       * and rethink without losing the tags.
  635.       */
  636.         if (tagged > 0) {
  637.             for (i=leftoff; i < message_count; i++) {
  638.                 if (ison(aliases[i]->status, TAGGED)) {
  639.                     clearit(aliases[i]->status, TAGGED);
  640.                     show_msg_tag(i);
  641.                 }
  642.             }
  643.         }
  644.         return(1);
  645.     }
  646.     else {
  647.         return(0);
  648.     }
  649.  
  650. }
  651.  
  652. int
  653. add_current_alias()
  654. {
  655. /*
  656.  *    Alias the current message to the specified name and
  657.  *    add it to the alias text file, for processing as
  658.  *    the user leaves the program.
  659.  *
  660.  *    Returns non-zero iff alias actually added to file.
  661.  */
  662.  
  663.     char aliasname[SLEN], firstname[SLEN], lastname[SLEN];
  664.     char comment[SLEN], address1[LONG_STRING], buffer[SLEN];
  665.     char comment_buff[LONG_STRING];
  666.     char *chspace, *bufptr;
  667.     struct header_rec *current_header;
  668.  
  669.     static char bad_punc[] = ",.:;";
  670.     char *punc_ptr;
  671.     int i, match;
  672.     int replace, to_replace;
  673.  
  674.     if (current_mail_message == 0) {
  675.      dprint(4, (debugfile, 
  676.         "Add current alias called without any current message!\n"));
  677.      error(catgets(elm_msg_cat, AliasesSet, AliasesNoMessage,
  678.         "No message to alias to!"));
  679.      return(0);
  680.     }
  681.     current_header = headers[current_mail_message - 1];
  682.     
  683.     strcpy(buffer, catgets(elm_msg_cat, AliasesSet, AliasesCurrentMessage,
  684.         "Current message address aliased to: "));
  685.     PutLine0(LINES-2,0, buffer);
  686.     CleartoEOLN();
  687.     *aliasname = '\0';
  688.     if ((replace = get_aliasname(aliasname, buffer, &to_replace)) < 0) {
  689.         dprint(3, (debugfile, 
  690.             "Aliasname [%s] was rejected in add_current_alias\n",
  691.             aliasname));
  692.         ClearLine(LINES-2);
  693.         return(0);
  694.     }
  695.  
  696.     /* use full name in current message for default comment */
  697.     tail_of(current_header->from, comment_buff, current_header->to);
  698.     if(index(comment_buff, (int)'!') || index(comment_buff, (int)'@'))
  699.       /* never mind - it's an address not a full name */
  700.       *comment_buff = '\0';
  701.  
  702. /*
  703.  *    Try to break up the From: comment into firstname, lastname, and
  704.  *    any other text.  This is based on the fact that many address
  705.  *    comments are pretty straightforward.  This will break on many
  706.  *    situations.  Should handle:
  707.  *        (Robert Howard)
  708.  *        (Robert L. Howard)
  709.  *        (Robert Howard, Georgia Tech)
  710.  *    pretty well.  Will break on:
  711.  *        (The Voice of Reason)
  712.  *        and others....
  713.  */
  714.  
  715.     *firstname = '\0';
  716.     *lastname = '\0';
  717.     *comment = '\0';
  718.     if (strlen(comment_buff) != 0) {    /* There is something. */
  719.         bufptr = comment_buff;
  720.         while (*bufptr == SPACE) bufptr++;    /* Always strip leading WS */
  721.         if ((chspace = index(bufptr, (int) SPACE)) != NULL) {
  722.        /*
  723.         *   A space means that there is at least (firstname lastname)
  724.         *   Get firstname and move bufptr.
  725.         */
  726.             *chspace = '\0';
  727.             strcpy(firstname, bufptr);
  728.             bufptr = chspace + 1;            /* Move the pointer */
  729.             while (*bufptr == SPACE) bufptr++;
  730.         }
  731.  
  732. above:        if ((chspace = index(bufptr, (int) SPACE)) != NULL) {
  733.        /*
  734.         *   Another space means a third+ word.  We either have:
  735.         *       1. Word 3+ is a comment, or
  736.         *       2. Word 2 is a middle initial (word 3 is lastname).
  737.         *   Check and see.
  738.         */
  739.             *chspace = '\0';
  740.             if ((strlen(bufptr) == 1) ||
  741.                 (strlen(bufptr) == 2  && *(bufptr+1) == '.')) {
  742.            /*
  743.             *   If the second word is either a single
  744.             *   character or a character followed by '.' it was
  745.             *   probably a middle initial.  Add it to firstname
  746.             *   and shift.
  747.             */
  748.                 strcat(firstname, " ");
  749.                 strcat(firstname, bufptr);
  750.                 bufptr = chspace + 1;        /* Move the pointer */
  751.                 while (*bufptr == SPACE) bufptr++;
  752.                 goto above;
  753.             }
  754.             strcpy(lastname, bufptr);
  755.             bufptr = chspace + 1;            /* Move the pointer */
  756.             while (*bufptr == SPACE) bufptr++;
  757.             strcpy(comment, bufptr);
  758.         }
  759.         else {
  760.        /*
  761.         *   Only a lastname left.
  762.         */
  763.             strcpy(lastname, bufptr);
  764.         }
  765.  
  766.     /*
  767.      *  Finally, get any puctuation characters off the end of
  768.      *  lastname.
  769.      */
  770.         match = TRUE;
  771.         for (i = strlen(lastname) - 1; match && i>0; i--) {
  772.             match = FALSE;
  773.             for (punc_ptr = bad_punc; *punc_ptr != '\0'; punc_ptr++) {
  774.                 if (lastname[i] == *punc_ptr) {
  775.                     lastname[i] = '\0';
  776.                     match = TRUE;
  777.                     break;
  778.                 }
  779.             }
  780.         }
  781.     }
  782.  
  783.     get_realnames(aliasname, firstname, lastname, comment, buffer);
  784.  
  785.     /* grab the return address of this message */
  786.     main_state(); /* toggle main state so that message_count is right */
  787.     get_return(address1, current_mail_message-1);
  788.     main_state(); /* toggle main state back to alias mode */
  789.     strcpy(address1, strip_parens(address1));    /* remove parens! */
  790.  
  791.     return(ask_accept(aliasname, firstname, lastname, comment, address1,
  792.             buffer, replace, to_replace));
  793.  
  794. }
  795.  
  796. add_to_alias_text(aliasname, firstname, lastname, comment, address)
  797. char *aliasname, *firstname, *lastname, *comment, *address;
  798. {
  799. /*
  800.  *    Add the data to the user alias text file.
  801.  *
  802.  *    Return zero if we succeeded, 1 if not.
  803.  */
  804.     
  805.     FILE *file;
  806.     char fname[SLEN];
  807.     char buffer[SLEN];
  808.     int  err;
  809.     
  810.     sprintf(fname,"%s/%s", home, ALIAS_TEXT);
  811.     
  812.     save_file_stats(fname);
  813.     if ((file = fopen(fname, "a")) == NULL) {
  814.       err = errno;
  815.       dprint(2, (debugfile, 
  816.          "Failure attempting to add alias to file %s within %s",
  817.            fname, "add_to_alias_text"));
  818.       dprint(2, (debugfile, "** %s **\n", error_description(err)));
  819.       error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntOpenAdd,
  820.          "Couldn't open %s to add new alias!"), fname);
  821.       return(1);
  822.     }
  823.  
  824.     if (strlen(firstname) == 0) {
  825.         strcpy(buffer, lastname);  
  826.     }
  827.     else {
  828.         sprintf(buffer, "%s; %s", lastname, firstname);
  829.     }
  830.     if (strlen(comment) != 0) {
  831.         strcat(buffer, ", ");
  832.         strcat(buffer, comment);
  833.     }
  834.     if (fprintf(file,"%s = %s = %s\n", aliasname, buffer, address) == EOF) {
  835.         err = errno;
  836.         dprint(2, (debugfile,
  837.                "Failure attempting to write alias to file within %s",
  838.                fname, "add_to_alias_text"));
  839.         dprint(2, (debugfile, "** %s **\n", error_description(err)));
  840.         error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntWrite,
  841.            "Couldn't write alias to file %s!"), fname);
  842.         fclose(file);
  843.         return(1);
  844.     }
  845.  
  846.     fclose(file);
  847.  
  848.     restore_file_stats(fname);
  849.  
  850.     return(0);
  851. }
  852.  
  853. delete_from_alias_text(name, num_to_delete)
  854. char **name;
  855. int num_to_delete;
  856. {
  857. /*
  858.  *    Delete the data from the user alias text file.
  859.  *
  860.  *    Return zero if we succeeded, 1 if not.
  861.  */
  862.     
  863.     FILE *file, *tmp_file;
  864.  
  865.     char fname[SLEN], tmpfname[SLEN];
  866.     char line_in_file[LONG_STRING];
  867.     char rest_of_line[LONG_STRING];
  868.     char *s, *rest;
  869.  
  870.     register int i;
  871.     int num_aliases;
  872.     int delete_continues;
  873.     int err;
  874.  
  875.     delete_continues = FALSE;
  876.  
  877.     for (i=0; i < num_to_delete; i++)
  878.       strcat(name[i], ","); 
  879.  
  880.     sprintf(fname,"%s/%s", home, ALIAS_TEXT);
  881.     sprintf(tmpfname,"%s/%s.t", home, ALIAS_TEXT);
  882.     
  883.     save_file_stats(fname);
  884.  
  885.     if ((file = fopen(fname, "r")) == NULL) {
  886.       err = errno;
  887.       dprint(2, (debugfile, 
  888.          "Failure attempting to delete alias from file %s within %s",
  889.            fname, "delete_from_alias_text"));
  890.       dprint(2, (debugfile, "** %s **\n", error_description(err)));
  891.       error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntOpenDelete,
  892.          "Couldn't open %s to delete alias!"), fname);
  893.       return(1);
  894.     }
  895.  
  896.     if ((tmp_file = fopen(tmpfname, "w")) == NULL) {
  897.       err = errno;
  898.       dprint(2, (debugfile, 
  899.          "Failure attempting to open temp file %s within %s",
  900.            tmpfname, "delete_from_alias_text"));
  901.       dprint(2, (debugfile, "** %s **\n", error_description(err)));
  902.       error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntOpenTemp,
  903.            "Couldn't open temp file %s to delete alias!"), tmpfname);
  904.       return(1);
  905.     }
  906.  
  907.     while (mail_gets(line_in_file, sizeof(line_in_file), file) != 0)
  908.     {
  909.       if (! whitespace(line_in_file[0])) {
  910.         delete_continues = FALSE;
  911.         if (line_in_file[0] != '#') {
  912.           if (num_aliases = parse_aliases(line_in_file, rest_of_line)) {
  913.             for (i=0; i < num_to_delete && num_aliases; i++) {
  914.               if ((s = strstr(line_in_file, name[i])) != NULL) {
  915. /*
  916.  *    Collapse the to be deleted alias out of line_in_file
  917.  */
  918.                 rest = index(s, (int)',');
  919.                 for (++rest; *rest; rest++)
  920.                   *s++ = *rest;
  921.                 *s = '\0';
  922.                 num_aliases--;
  923.               }
  924.             }
  925.             if (num_aliases) {
  926.               *(line_in_file + strlen(line_in_file) - 1) = ' ';
  927.               strcat(line_in_file, rest_of_line);
  928.             }
  929.             else {
  930.               delete_continues = TRUE;
  931.             }
  932.           }
  933.         }
  934.       }
  935.       if (! delete_continues) {
  936.         if (fprintf(tmp_file,"%s", line_in_file) == EOF) {
  937.           err = errno;
  938.           dprint(2, (debugfile,
  939.         "Failure attempting to write to temp file %s within %s",
  940.         tmpfname, "delete_from_alias_text"));
  941.           dprint(2, (debugfile, "** %s **\n", error_description(err)));
  942.           error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntWriteTemp,
  943.         "Couldn't write to temp file %s!"), tmpfname);
  944.           fclose(file);
  945.           fclose(tmp_file);
  946.           unlink(tmpfname);
  947.           return(1);
  948.         }
  949.       }
  950.     }
  951.     fclose(file);
  952.     fclose(tmp_file);
  953.     if (rename(tmpfname, fname) != 0)
  954.     {
  955.         error1(catgets(elm_msg_cat, AliasesSet, AliasesCouldntRenameTemp,
  956.             "Couldn't rename temp file %s after deleting alias!"), tmpfname);
  957.         return(1);
  958.     }
  959.  
  960.     restore_file_stats(fname);
  961.  
  962.     return(0);
  963. }
  964.  
  965. alias()
  966. {
  967. /*
  968.  *    Work with alias commands...
  969.  */
  970.  
  971.     char name[NLEN], *address, ch, buffer[SLEN];
  972.     char *commap;
  973.     int  key_offset;        /** Position offset within keyboard string   **/
  974.     static int  newaliases = 0;
  975.     int  i, j;
  976.     int nutitle = 0;
  977.     int too_long;
  978.  
  979. /*
  980.  *    We're going to try to match the way elm does it at
  981.  *     he main menu.  I probably won't be able to use any
  982.  *    main menu routines, but I will "borrow" from them. RLH
  983.  */
  984.  
  985.     main_state();        /* Save globals for return to main menu */
  986.  
  987.     open_alias_files();    /* First, read the alias files. RLH */
  988.  
  989.     alias_screen(newaliases);
  990.     define_softkeys(ALIAS);
  991.  
  992.     while (1) {
  993.  
  994. #ifdef SIGWINCH
  995.       if (resize_screen) {
  996.         int    newLINES, newCOLUMNS;
  997.  
  998.         ScreenSize(&newLINES, &newCOLUMNS);
  999.         resize_screen = 0;
  1000.         if (newLINES != LINES || newCOLUMNS != COLUMNS) {
  1001.           LINES = newLINES, COLUMNS = newCOLUMNS;
  1002. #define max(a,b)           ((a) < (b) ? (b) : (a))
  1003.           if (mini_menu)
  1004.         headers_per_page = max (LINES - 13, 1);
  1005.           else
  1006.         headers_per_page = max (LINES -     8, 1);      /* 5 more headers! */
  1007. #undef max
  1008.           redraw++;
  1009.         }
  1010.       }
  1011.       else redraw = 0;
  1012. #else
  1013.           redraw = 0;
  1014. #endif
  1015.       nucurr = 0;
  1016.       nufoot = 0;
  1017.  
  1018.       prompt(Prompt);
  1019.       CleartoEOLN();
  1020.       ch = ReadCh();
  1021.       MoveCursor(LINES-3,strlen(Prompt)); CleartoEOS();
  1022.       
  1023.       dprint(3, (debugfile, "\n-- Alias command: %c\n\n", ch));
  1024.  
  1025.       switch (ch) {
  1026.         case '?': redraw += alias_help();            break;
  1027.  
  1028.         case '$': PutLine0(LINES-3, strlen(Prompt),
  1029.                  catgets(elm_msg_cat, AliasesSet, AliasesResync,
  1030.                     "Resynchronize aliases..."));
  1031.                /*
  1032.                 * Process deletions and then see if we need to
  1033.                 * re-run the "newalias" routine.
  1034.                 */
  1035.               if (resync_aliases(newaliases)) {
  1036.                 install_aliases();
  1037.                     newaliases = 0;
  1038.                 redraw++;
  1039.               }
  1040.               break;
  1041.  
  1042.         case 'a': PutLine0(LINES-3, strlen(Prompt),
  1043.                  catgets(elm_msg_cat, AliasesSet, AliasesAddCurrent,
  1044.                     "Add address from current message..."));
  1045.               clear_error();
  1046.               if (add_current_alias()) {
  1047.                   newaliases++;
  1048.                   nutitle++;
  1049.               }
  1050.               break;
  1051.  
  1052.         case 'c':
  1053.                   if (current > 0) {
  1054.                       PutLine0(LINES-3, strlen(Prompt),
  1055.                   catgets(elm_msg_cat,
  1056.                                   AliasesSet, AliasesReplaceCurrent,
  1057.                                   "Replace current alias in database..."));
  1058.                   clear_error();
  1059.                   if (add_alias(TRUE, current-1)) {
  1060.                       newaliases++;
  1061.                       nutitle++;
  1062.                   }
  1063.                   }
  1064.                   else {
  1065.                   error(catgets(elm_msg_cat,
  1066.                               AliasesSet, AliasesNoneToReplace,
  1067.                   "Warning: no aliases to replace!"));
  1068.                   }
  1069.               break;
  1070.  
  1071.         case 'e': PutLine1(LINES-3, strlen(Prompt),
  1072.                       catgets(elm_msg_cat, AliasesSet, AliasesEdit,
  1073.                           "Edit %s..."), ALIAS_TEXT);
  1074.                /*
  1075.                 * Process aliases.text for deletions, etc.  You
  1076.                 * have to do this *before* checking current because
  1077.                 * all aliases could be marked for deletion.
  1078.                 */
  1079.                   (void) resync_aliases(newaliases);
  1080.                   if (edit_aliases_text()) {
  1081.                       newaliases = 0;
  1082.                   }
  1083.                   if (cursor_control) {
  1084.                       transmit_functions(ON);    /* insurance */
  1085.                   }
  1086.               redraw++;
  1087.               break;
  1088.  
  1089.         case 'm':
  1090.                   if (current > 0) {
  1091.                       PutLine0(LINES-3, strlen(Prompt),
  1092.                           catgets(elm_msg_cat, AliasesSet, AliasesMail,
  1093.                               "Mail..."));
  1094.                       redraw += a_sendmsg(TRUE,allow_forms);
  1095.                   }
  1096.                   else {
  1097.                   error(catgets(elm_msg_cat,
  1098.                               AliasesSet, AliasesNoneToMail,
  1099.                   "Warning: no aliases to send mail to!"));
  1100.                   }
  1101.               break;
  1102.  
  1103.         case 'n': PutLine0(LINES-3, strlen(Prompt),
  1104.                  catgets(elm_msg_cat, AliasesSet, AliasesAddNew,
  1105.                          "Add a new alias to database..."));
  1106.               clear_error();
  1107.               if (add_alias(FALSE, -1)) {
  1108.                   newaliases++;
  1109.                   nutitle++;
  1110.               }
  1111.               break;
  1112.  
  1113.         case 'q':
  1114.         case 'Q':
  1115.         case 'i':
  1116.         case 'I':
  1117.         case 'r':
  1118.         case 'R': PutLine0(LINES-3, strlen(Prompt),
  1119.                  catgets(elm_msg_cat, AliasesSet, AliasesAddReturn,
  1120.                     "Return to main menu..."));
  1121.                /*
  1122.                 * leaving the alias system.  Must check for
  1123.                 * pending deletes, etc.  prompt is set to FALSE
  1124.                 * on uppercase letters so that deletions are
  1125.                 * NOT queried.
  1126.                 */
  1127.                   if (delete_aliases(newaliases, islower(ch))) {
  1128.                     install_aliases();
  1129.                     newaliases = 0;
  1130.                   }
  1131.               clear_error();
  1132.               main_state();        /* Done with aliases. */
  1133.               return;
  1134.  
  1135.         case RETURN:
  1136.         case LINE_FEED:
  1137.         case SPACE:
  1138.         case 'v':
  1139.               if (newaliases) {        /* Need this ?? */
  1140.                   error(catgets(elm_msg_cat,
  1141.                               AliasesSet, AliasesNotInstalled,
  1142.                   "Warning: new aliases not installed yet!"));
  1143.                   }
  1144.  
  1145.                   if (current > 0) {
  1146.                       if (aliases[current-1]->type & GROUP) {
  1147.                           PutLine1(LINES-1, 0, catgets(elm_msg_cat,
  1148.                                   AliasesSet, AliasesGroupAlias,
  1149.                       "Group alias: %-60.60s"),
  1150.                               aliases[current-1]->address);
  1151.                   }
  1152.                   else {
  1153.                           PutLine1(LINES-1, 0, catgets(elm_msg_cat,
  1154.                                   AliasesSet, AliasesAliasedAddress,
  1155.                       "Aliased address: %-60.60s"), 
  1156.                               aliases[current-1]->address);
  1157.                   }
  1158.               }
  1159.                   else {
  1160.                   error(catgets(elm_msg_cat,
  1161.                               AliasesSet, AliasesNoneToView,
  1162.                   "Warning: no aliases to view!"));
  1163.               }
  1164.               break;
  1165.  
  1166.         case 'x':
  1167.         case 'X': PutLine0(LINES-3, strlen(Prompt),
  1168.                  catgets(elm_msg_cat, AliasesSet, AliasesAddReturn,
  1169.                     "Return to main menu..."));
  1170.                   exit_alias();
  1171.               clear_error();
  1172.               main_state();        /* Done with aliases. */
  1173.               return;
  1174.  
  1175.         case 'f':
  1176.         case 'F':
  1177.                   if (current > 0) {
  1178.                   clear_error();
  1179.                   strcpy(name, aliases[current-1]->alias);
  1180.                   if (ch == 'F') {
  1181.                       strcpy(buffer, catgets(elm_msg_cat,
  1182.                                   AliasesSet, AliasesFullyExpanded,
  1183.                       "Fully expand alias: "));
  1184.                       PutLine0(LINES-2,0, buffer);
  1185.                       CleartoEOS();
  1186.                       optionally_enter(name, LINES-2, strlen(buffer),
  1187.                       FALSE, FALSE);
  1188.                   }
  1189.                       too_long = FALSE;
  1190.                   address = get_alias_address(name, TRUE, &too_long);
  1191.                   if (address != NULL) {
  1192.                       while (TRUE) {
  1193.                               ClearScreen();
  1194.                       PutLine1(2,0, catgets(elm_msg_cat,
  1195.                                       AliasesSet, AliasesAliasedFull,
  1196.                       "Aliased address for:\t%s\n\r"),
  1197.                                   name);
  1198.                           i = 4;
  1199.                           while (i < LINES-2) {
  1200.                               if ((commap = index(address, (int)','))
  1201.                                               == NULL) {
  1202.                                   PutLine0(i, 4, address);
  1203.                                   break;
  1204.                               }
  1205.                               *commap = '\0';
  1206.                               PutLine0(i++, 4, address);
  1207.                               address = commap+2;
  1208.                           }
  1209.                               PutLine0(LINES-1, 0, catgets(elm_msg_cat,
  1210.                                       AliasesSet, AliasesPressReturn,
  1211.                       "Press <return> to continue."));
  1212.                       (void) getchar();
  1213.                           if (commap == NULL) {
  1214.                           redraw++;
  1215.                               break;
  1216.                           }
  1217.                       }
  1218.                   }
  1219.                       else if (! too_long) {
  1220.                   error(catgets(elm_msg_cat,
  1221.                                   AliasesSet, AliasesNotFound,
  1222.                       "Not found."));
  1223.                   }
  1224.               }
  1225.                   else {
  1226.                   error(catgets(elm_msg_cat,
  1227.                               AliasesSet, AliasesNoneToView,
  1228.                   "Warning: no aliases to view!"));
  1229.               }
  1230.               break;
  1231.  
  1232.      /*
  1233.       * None of the menu specific commands were chosen, therefore
  1234.       * it must be a "motion" command (or an error).
  1235.       */
  1236.         default    : motion(ch);
  1237.  
  1238.       }
  1239.  
  1240.       if (redraw) {            /* Redraw screen if necessary */
  1241.           alias_screen(newaliases);
  1242.           nutitle = 0;
  1243.       }
  1244.  
  1245.       if (nutitle) {        /* Redraw title if necessary */
  1246.           alias_title(newaliases);
  1247.           nutitle = 0;
  1248.       }
  1249.  
  1250.       check_range();
  1251.  
  1252.       if (nucurr == NEW_PAGE)
  1253.         show_headers();
  1254.       else if (nucurr == SAME_PAGE)
  1255.         show_current();
  1256.       else if (nufoot) {
  1257.         if (mini_menu) {
  1258.           MoveCursor(LINES-7, 0);  
  1259.               CleartoEOS();
  1260.           show_alias_menu();
  1261.         }
  1262.         else {
  1263.           MoveCursor(LINES-4, 0);
  1264.           CleartoEOS();
  1265.         }
  1266.         show_last_error();    /* for those operations that have to
  1267.                  * clear the footer except for a message.
  1268.                  */
  1269.       }
  1270.     }            /* BIG while loop... */
  1271. }
  1272.  
  1273. void
  1274. install_aliases()
  1275. {
  1276. /*
  1277.  *    Run the 'newalias' program and update the
  1278.  *    aliases before going back to the main program! 
  1279.  *
  1280.  *    No return value.....
  1281.  */
  1282.  
  1283.     int na;
  1284.     char itextfile[SLEN], odatafile[SLEN];
  1285.     char buffer[SLEN];
  1286.  
  1287.  
  1288.     error(catgets(elm_msg_cat, AliasesSet, AliasesUpdating,
  1289.         "Updating aliases..."));
  1290.     if (sleepmsg > 0)
  1291.         sleep(sleepmsg);
  1292.  
  1293.     sprintf(itextfile, "%s/%s", home, ALIAS_TEXT);
  1294.     sprintf(odatafile, "%s/%s", home, ALIAS_DATA);
  1295.  
  1296. /*
  1297.  *    We need to unlimit everything since aliases are 
  1298.  *     eing read in from scratch.
  1299.  */
  1300.     selected = 0;
  1301.  
  1302.     na = do_newalias(itextfile, odatafile, TRUE, FALSE);
  1303.     if (na >= 0) {
  1304.         error1(catgets(elm_msg_cat, AliasesSet, AliasesReReading,
  1305.           "Processed %d aliases.  Re-reading the database..."), na);
  1306.         if (sleepmsg > 0)
  1307.         sleep(sleepmsg);
  1308.         open_alias_files();
  1309.         set_error(catgets(elm_msg_cat, AliasesSet, AliasesUpdatedOK,
  1310.           "Aliases updated successfully."));
  1311.     }
  1312. }
  1313.  
  1314. alias_help()
  1315. {
  1316. /*
  1317.  *    Help section for the alias menu...
  1318.  *
  1319.  *    Return non-0 if main part of screen overwritten, else 0
  1320.  */
  1321.     
  1322.     char ch;
  1323.     int  redraw=0;
  1324.     char *alias_prompt;
  1325.     
  1326.     
  1327.     if (mini_menu)
  1328.         alias_prompt = catgets(elm_msg_cat, AliasesSet, AliasesShortKey,
  1329.             "Key: ");
  1330.     else
  1331.         alias_prompt = catgets(elm_msg_cat, AliasesSet, AliasesLongKey,
  1332.             "Key you want help for: ");
  1333.  
  1334.     MoveCursor(LINES-3, 0);    CleartoEOS();
  1335.  
  1336.     if (mini_menu) {
  1337.       Centerline(LINES-3, catgets(elm_msg_cat, AliasesSet, AliasesKeyMenu,
  1338.  "Press the key you want help for, '?' for a key list, or '.' to exit help"));
  1339.     }
  1340.  
  1341.     lower_prompt(alias_prompt);
  1342.  
  1343.     while ((ch = ReadCh()) != '.') {
  1344.       switch(ch) {
  1345.         case '?' : display_helpfile(ALIAS_HELP);    
  1346.                redraw++;
  1347.                return(redraw);
  1348.  
  1349.         case '$': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpDollar,
  1350. "$ = Force resynchronization of aliases, processing additions and deletions."));
  1351.               break;
  1352.  
  1353.         case '/': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpSlash,
  1354.             "/ = Search for specified name or alias in list."));
  1355.               break;
  1356.  
  1357.         case RETURN:
  1358.         case LINE_FEED:
  1359.         case SPACE:
  1360.         case 'v': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpv,
  1361.         "v = View the address for the currently selected alias."));
  1362.               break;
  1363.     
  1364.         case 'a': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpa,
  1365.         "a = Add (return) address of current message to alias database."));
  1366.               break;
  1367.  
  1368.         case 'c': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpc,
  1369. "c = Change current user alias, modifying alias database at next resync."));
  1370.               break;
  1371.  
  1372.         case 'd': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpd,
  1373.         "d = Mark the current alias for deletion from alias database."));
  1374.               break;
  1375.  
  1376.         case ctrl('D'): error(catgets(elm_msg_cat, AliasesSet, AliasesHelpCtrlD,
  1377.         "^D = Mark for deletion user aliases matching specified pattern."));
  1378.               break;
  1379.  
  1380.         case 'e': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpe,
  1381.         "e = Edit the alias text file directly (will run newalias)."));
  1382.               break;
  1383.  
  1384.         case 'f': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpf,
  1385.         "f = Display fully expanded address of current alias."));
  1386.               break;
  1387.  
  1388.         case 'l': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpl,
  1389.         "l = Limit displayed aliases on the specified criteria."));
  1390.               break;
  1391.  
  1392.         case ctrl('L'): error(catgets(elm_msg_cat, AliasesSet, AliasesHelpCtrlL,
  1393.               "^L = Rewrite the screen."));
  1394.                   break;
  1395.  
  1396.         case 'm': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpm,
  1397.         "m = Send mail to the current or tagged aliases."));
  1398.               break;
  1399.  
  1400.         case 'n': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpn,
  1401. "n = Add a new user alias, adding to alias database at next resync."));
  1402.               break;
  1403.  
  1404.         case 'r':
  1405.         case 'q':
  1406.         case 'i': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpi,
  1407.               "r,q,i = Return from alias menu (with prompting)."));
  1408.                  break;
  1409.               
  1410.         case 'R':
  1411.         case 'Q':
  1412.         case 'I': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpQ,
  1413.               "R,Q,I = Return from alias menu (no prompting)."));
  1414.                  break;
  1415.               
  1416.         case 't': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpt,
  1417.               "t = Tag current alias for further operations."));
  1418.               break;
  1419.     
  1420.         case 'T': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpT,
  1421.               "T = Tag current alias and go to next alias."));
  1422.               break;
  1423.     
  1424.         case ctrl('T'): error(catgets(elm_msg_cat, AliasesSet, AliasesHelpCtrlT,
  1425.         "^T = Tag aliases matching specified pattern."));
  1426.               break;
  1427.  
  1428.         case 'u': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpu,
  1429.         "u = Unmark the current alias for deletion from alias database."));
  1430.               break;
  1431.  
  1432.         case ctrl('U'): error(catgets(elm_msg_cat, AliasesSet, AliasesHelpCtrlU,
  1433. "^U = Mark for undeletion user aliases matching specified pattern."));
  1434.               break;
  1435.  
  1436.         case 'x':
  1437.         case 'X': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpX,
  1438.         "x = Exit from alias menu, abandoning any pending deletions."));
  1439.                  break;
  1440.  
  1441.         default : error(catgets(elm_msg_cat, AliasesSet, AliasesHelpNoHelp,
  1442.             "That key isn't used in this section."));
  1443.                  break;
  1444.       }
  1445.       lower_prompt(alias_prompt);
  1446.     }
  1447.  
  1448.     /* Remove help lines */
  1449.     MoveCursor(LINES-3, 0);    CleartoEOS();
  1450.     return(redraw);
  1451. }
  1452.  
  1453. get_aliases(are_in_aliases)
  1454. int are_in_aliases;
  1455. {
  1456. /*
  1457.  *    Get all the system and user alias info
  1458.  *
  1459.  *    If we get this far, we must be needing to re-read from
  1460.  *    at least one data file.  Unfortunately that means we 
  1461.  *    really need to read both since the aliases may be sorted
  1462.  *    and all mixed up...  :-(
  1463.  */
  1464.  
  1465.     char fname[SLEN];
  1466.     register int i = -1;
  1467.     int dups = 0;
  1468.  
  1469.     current = 0;
  1470.     num_duplicates = 0;
  1471. /*
  1472.  *    Read from user data file if it is open.
  1473.  */
  1474.     if (user_hash != NULL) {
  1475.         dprint(6, (debugfile,
  1476.               "About to read user data file = %d.\n",
  1477.                   user_hash->dbz_basef));
  1478.         fseek(user_hash->dbz_basef, 0L, 0);
  1479.         while (get_one_alias(user_hash, current)) {
  1480.         dprint(8, (debugfile, "%d\t%s\t%s\n", current+1,
  1481.                        aliases[current]->alias,
  1482.                        aliases[current]->address));
  1483.  
  1484.         current++;
  1485.         }
  1486.     }
  1487.     message_count = current;    /* Needed for find_alias() */
  1488.  
  1489. /*
  1490.  *    Read from system data file if it is open.
  1491.  */
  1492.     if (system_hash != NULL) {
  1493.         dprint(6, (debugfile,
  1494.               "About to read system data file = %d.\n",
  1495.                   system_hash->dbz_basef));
  1496.         fseek(system_hash->dbz_basef, 0L, 0);
  1497.         while (get_one_alias(system_hash, current)) {
  1498.         /*
  1499.          *  If an identical user alias is found, we may
  1500.          *  not want to display it, so we had better mark it.
  1501.          */
  1502.         if (find_alias(aliases[current]->alias, USER) >= 0) {
  1503.             setit(aliases[current]->type, DUPLICATE);
  1504.             dups++;
  1505.             setit(aliases[current]->status, URGENT);
  1506.                     /* Not really, I want the U for User */
  1507.             dprint(6, (debugfile,
  1508.                    "System alias %s is same as user alias.\n",
  1509.                    aliases[current]->alias));
  1510.         }
  1511.         dprint(8, (debugfile, "%d\t%s\t%s\n", current+1,
  1512.                        aliases[current]->alias,
  1513.                        aliases[current]->address));
  1514.  
  1515.         current++;
  1516.         }
  1517.         num_duplicates = dups;
  1518.     }
  1519.     message_count = current - num_duplicates;
  1520.  
  1521.     if (!mail_only && !check_only && message_count) {
  1522.         current = 0;
  1523.         sort_aliases((message_count+num_duplicates), FALSE, are_in_aliases);
  1524.         current = 1;
  1525.         if (are_in_aliases) {
  1526.             (void) get_page(current);
  1527.         }
  1528.     }
  1529.  
  1530. }
  1531.  
  1532. get_one_alias(db, current)
  1533. DBZ *db;
  1534. int current;
  1535. {
  1536. /*
  1537.  *    Get an alias (name, address, etc.) from the data file
  1538.  */
  1539.  
  1540.     long new_max;
  1541.     register struct alias_rec    **new_aliases, *a;
  1542.     struct alias_rec    ar;
  1543.     FILE *data_file = db->dbz_basef;
  1544.  
  1545.     if(read_one_alias(db, &ar) == 0) {
  1546.         return(0);
  1547.     }
  1548.  
  1549.     if (current >= max_aliases) {
  1550.         new_max = max_aliases + KLICK;
  1551.         if (max_aliases == 0)
  1552.         new_aliases = (struct alias_rec **)
  1553.             malloc(new_max * sizeof(struct alias_rec *));
  1554.         else
  1555.         new_aliases = (struct alias_rec **)
  1556.             realloc((char *) aliases,
  1557.             new_max * sizeof(struct alias_rec *));
  1558.  
  1559.         if (new_aliases == NULL) {
  1560.         error1(catgets(elm_msg_cat, AliasesSet, AliasesErrorMemory,
  1561.       "\n\r\n\rCouldn't allocate enough memory! Alias #%d.\n\r\n\r"),
  1562.             current);
  1563.         return(0);
  1564.         }
  1565.         aliases = new_aliases;
  1566.         while (max_aliases < new_max)
  1567.         aliases[max_aliases++] = NULL;
  1568.     }
  1569.  
  1570.  
  1571.     if (aliases[current] != NULL) {
  1572.         free((char *) aliases[current]);
  1573.         aliases[current] = NULL;
  1574.     }
  1575.  
  1576.     if ((a = (struct alias_rec *)
  1577.         malloc(sizeof(ar) + ar.length)) == NULL) {
  1578.         error1(catgets(elm_msg_cat, AliasesSet, AliasesErrorMemory,
  1579.       "\n\r\n\rCouldn't allocate enough memory! Alias #%d.\n\r\n\r"),
  1580.             current);
  1581.         return(0);
  1582.         }
  1583.  
  1584.     aliases[current] = a;
  1585.     fread((char *) (a + 1), ar.length, 1, data_file);
  1586.     *a = ar;
  1587. #ifdef CRAY
  1588.     a->alias = (int) a->alias + (char *) (a + 1);
  1589.     a->last_name = (int) a->last_name + (char *) (a + 1);
  1590.     a->name = (int) a->name + (char *) (a + 1);
  1591.     a->comment = (int) a->comment + (char *) (a + 1);
  1592.     a->address = (int) a->address + (char *) (a + 1);
  1593. #else
  1594.     new_max = (long) (a + 1);
  1595.  
  1596.     a->alias += new_max;
  1597.     a->last_name += new_max;
  1598.     a->name += new_max;
  1599.     a->comment += new_max;
  1600.     a->address += new_max;
  1601. #endif
  1602.     a->length = current;   
  1603.   
  1604.  
  1605.     return(1);
  1606. }
  1607.  
  1608. main_state()
  1609. {
  1610. /*    Save the globals that are shared for both menus
  1611.  *    so that we can return to the main menu without
  1612.  *    "tragedy".
  1613.  */
  1614.  
  1615.     static int alias_count = 0,    alias_current = 0, alias_last = -1,
  1616.                alias_selected = 0, alias_page = 0;
  1617.     static int main_count = 0,     main_current = 0, main_last = -1,
  1618.                main_selected = 0,  main_page = 0;
  1619.  
  1620.     if (inalias) {            /* Restore the settings */
  1621.         alias_count = message_count;
  1622.         alias_current = current;
  1623.         alias_last = last_current;
  1624.         alias_selected = selected;
  1625.         alias_page = header_page;
  1626.  
  1627.         message_count = main_count;
  1628.         current = main_current;
  1629.         last_current = main_last;
  1630.         selected = main_selected;
  1631.         header_page = main_page;
  1632.  
  1633.         strcpy(item, catgets(elm_msg_cat, ElmSet, Elmitem, "message"));
  1634.         strcpy(items, catgets(elm_msg_cat, ElmSet, Elmitems, "messages"));
  1635.         strcpy(Item, catgets(elm_msg_cat, ElmSet, ElmItem, "Message"));
  1636.         strcpy(Items, catgets(elm_msg_cat, ElmSet, ElmItems, "Messages"));
  1637.         strcpy(Prompt, catgets(elm_msg_cat, ElmSet, ElmPrompt, "Command: "));
  1638.  
  1639.         dprint(3, (debugfile, "Leaving alias mode\n"));
  1640.         inalias = FALSE;
  1641.     }
  1642.     else {
  1643.         main_count = message_count;
  1644.         main_current = current;
  1645.         current_mail_message = current;
  1646.         main_last = last_current;
  1647.         main_selected = selected;
  1648.         main_page = header_page;
  1649.  
  1650.         message_count = alias_count;
  1651.         current = alias_current;
  1652.         last_current = alias_last;
  1653.         selected = alias_selected;
  1654.         header_page = alias_page;
  1655.  
  1656.         strcpy(item, catgets(elm_msg_cat, AliasesSet, Aliasesitem, "alias"));
  1657.         strcpy(items, catgets(elm_msg_cat, AliasesSet, Aliasesitems, "aliases"));
  1658.         strcpy(Item, catgets(elm_msg_cat, AliasesSet, AliasesItem, "Alias"));
  1659.         strcpy(Items, catgets(elm_msg_cat, AliasesSet, AliasesItems, "Aliases"));
  1660.         strcpy(Prompt, catgets(elm_msg_cat, AliasesSet, AliasesPrompt, "Alias: "));
  1661.  
  1662.         dprint(3, (debugfile, "Entered alias mode\n"));
  1663.         inalias = TRUE;
  1664.     }
  1665. }
  1666.  
  1667. int
  1668. parse_aliases(buffer, remainder)
  1669. char *buffer, *remainder;
  1670. {
  1671. /*
  1672.  *    This routine will parse out the individual aliases present
  1673.  *    on the line passed in buffer.  This involves:
  1674.  *
  1675.  *    1. Testing for an '=' to make sure this is an alias entry.
  1676.  *
  1677.  *    2. Setting remainder to point to the rest of the line starting
  1678.  *       at the '=' (for later rewriting if needed).
  1679.  *
  1680.  *    3. Parsing the aliases into an string padded with ',' at 
  1681.  *       the end.
  1682.  *
  1683.  *    4. Returning the number of aliases found (0 if test #1 fails).
  1684.  */
  1685.  
  1686.     char *s;
  1687.     int number;
  1688.  
  1689. /*    Check to see if an alias */
  1690.  
  1691.     if ((s = index(buffer, (int)'=')) == NULL)
  1692.       return (0);
  1693.  
  1694.     strcpy(remainder, s);        /* Save the remainder of the line */
  1695.  
  1696. /*    Terminate the list of aliases with a ',' */
  1697.  
  1698.     while (--s >= buffer && whitespace(*s)) ;
  1699.     *++s = ',';
  1700.     *++s = '\0';
  1701.  
  1702. /*    Lowercase everything */
  1703.  
  1704.     s = shift_lower(buffer);
  1705.     strcpy(buffer, s);
  1706.  
  1707. /*    Now, count the aliases */
  1708.  
  1709.     number = 0;
  1710.     for (s = buffer; *s; s++)
  1711.       if (*s == ',')
  1712.         number++;
  1713.  
  1714.     return (number);
  1715. }
  1716.  
  1717. int
  1718. get_aliasname(aliasname, buffer, duplicate)
  1719. char *aliasname, *buffer;
  1720. int *duplicate;
  1721. {
  1722.  
  1723. /*
  1724.  *    Have the user enter an aliasname, check to see if it
  1725.  *    is legal, then check for duplicates.  If a duplicate
  1726.  *    is found offer to replace existing alias.
  1727.  *
  1728.  *    Return values:
  1729.  *
  1730.  *    -1    Either the aliasname was zero length, had bad
  1731.  *        characters and was a duplicate which the user
  1732.  *        chose not to replace.
  1733.  *
  1734.  *    0    A new alias was entered successfully.
  1735.  *
  1736.  *    1    The entered alias was an existing USER alias
  1737.  *        that the user has chosen to replace.  In this
  1738.  *        case the alias to replace is passed back in
  1739.  *        in the variable 'duplicate'.
  1740.  */
  1741.  
  1742.     int loc;
  1743.  
  1744.     do {
  1745.         optionally_enter(aliasname, LINES-2, strlen(buffer), FALSE, FALSE);
  1746.     /*
  1747.      *  Return if nothing was entered.
  1748.      */
  1749.         if (strlen(aliasname) == 0) 
  1750.             return(-1);
  1751.  
  1752.     } while (check_alias(aliasname) == -1);
  1753.  
  1754.     clear_error();            /* Just in case */
  1755. /*
  1756.  *    Check to see if there is already a USER alias by this name.
  1757.  */
  1758.     if ((loc = find_alias(aliasname, USER)) >= 0) {
  1759.         dprint(3, (debugfile, 
  1760.              "Attempt to add a duplicate alias [%s] in get_aliasname\n",
  1761.              aliases[loc]->alias)); 
  1762.         if (aliases[loc]->type & GROUP )
  1763.             PutLine1(LINES-2,0, catgets(elm_msg_cat,
  1764.                     AliasesSet, AliasesAlreadyGroup,
  1765.                     "Already a group with name %s."), aliases[loc]->alias);
  1766.         else
  1767.             PutLine1(LINES-2,0, catgets(elm_msg_cat,
  1768.                     AliasesSet, AliasesAlreadyAlias,
  1769.                     "Already an alias for %s."), aliases[loc]->alias);
  1770.         CleartoEOLN();
  1771.         MCsprintf(buffer, catgets(elm_msg_cat,
  1772.                 AliasesSet, AliasesReplaceExisting,
  1773.                 "Replace existing alias? (%c/%c) "),
  1774.             *def_ans_yes, *def_ans_no);
  1775.      /*
  1776.       * If they don't want to replace the alias by that name
  1777.       * then just return.
  1778.       */
  1779.         if (want_to(buffer, *def_ans_no, LINES-3, 0) != *def_ans_yes)
  1780.             return(-1);
  1781.         *duplicate = loc;
  1782.         return(1);
  1783.     }
  1784. /*
  1785.  *    If they have elected to replace an existing alias then
  1786.  *    we assume that they would also elect to superceed a
  1787.  *    system alias by that name (since they have already
  1788.  *    done so).  So we don't even bother to check or ask.
  1789.  *
  1790.  *    Of course we do check if there was no USER alias match.
  1791.  */
  1792.     if ((loc = find_alias(aliasname, SYSTEM)) >= 0) {
  1793.         dprint(3, (debugfile, 
  1794.           "Attempt to add a duplicate system alias [%s] in get_aliasname\n",
  1795.           aliases[loc]->address)); 
  1796.       
  1797.         if( ! superceed_system(loc, buffer))
  1798.             return(-1);
  1799.     }
  1800.     return(0);
  1801.  
  1802. }
  1803.  
  1804. int
  1805. superceed_system(this_alias, buffer)
  1806. int this_alias;
  1807. char *buffer;
  1808. {
  1809.  
  1810.     PutLine2(LINES-2, 0, catgets(elm_msg_cat,
  1811.             AliasesSet, AliasesSystemAlias, "System (%6s) alias for %s."),
  1812.         alias_type(aliases[this_alias]->type), aliases[this_alias]->alias);
  1813.  
  1814.     MCsprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesSuperceed,
  1815.             "Superceed? (%c/%c) "), *def_ans_yes, *def_ans_no);
  1816. /*
  1817.  *    If they don't want to superceed the SYSTEM alias then
  1818.  *    return a FALSE.
  1819.  */
  1820.     return(want_to(buffer, *def_ans_no, LINES-3, 0) == *def_ans_yes);
  1821. }
  1822.  
  1823. void
  1824. get_realnames(aliasname, firstname, lastname, comment, buffer)
  1825. char *aliasname, *firstname, *lastname, *comment, *buffer;
  1826. {
  1827.  
  1828.     sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterLastName,
  1829.         "Enter last name for %s: "), aliasname);
  1830.     PutLine0(LINES-2,0, buffer);
  1831.     CleartoEOLN();
  1832.     optionally_enter(lastname, LINES-2, strlen(buffer), FALSE, FALSE);
  1833.  
  1834.     sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterFirstName,
  1835.         "Enter first name for %s: "), aliasname);
  1836.     PutLine0(LINES-2,0, buffer);
  1837.     CleartoEOLN();
  1838.     optionally_enter(firstname, LINES-2, strlen(buffer), FALSE, FALSE);
  1839.  
  1840.     if (strlen(lastname) == 0) {
  1841.         if (strlen(firstname) == 0) {
  1842.             strcpy(lastname, aliasname);  
  1843.         }
  1844.         else {
  1845.             strcpy(lastname, firstname);  
  1846.             *firstname = '\0';
  1847.         }
  1848.     }
  1849.  
  1850.     sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterComment,
  1851.         "Enter optional comment for %s: "), aliasname);
  1852.     PutLine0(LINES-2,0, buffer);
  1853.     optionally_enter(comment, LINES-2, strlen(buffer), FALSE, FALSE);
  1854.  
  1855. }
  1856.  
  1857. int
  1858. ask_accept(aliasname, firstname, lastname, comment, address, buffer,
  1859.     replace, replacement)
  1860. char *aliasname, *firstname, *lastname, *comment, *address, *buffer;
  1861. int replace, replacement;
  1862. {
  1863.  
  1864.     char ch;
  1865.     char *(old_alias[1]);
  1866. /*
  1867.  *    If firstname == lastname, they probably just took all
  1868.  *    the deafaults.  We *assume* they don't want lastname
  1869.  *    entered twice, so we will truncate it.
  1870.  */
  1871.     if (strcmp(firstname, lastname) == 0) {
  1872.         *firstname = '\0';
  1873.     }
  1874.  
  1875.     if (strlen(firstname) == 0) {
  1876.         strcpy(buffer, lastname);  
  1877.     }
  1878.     else {
  1879.         sprintf(buffer, "%s %s", firstname, lastname);
  1880.     }
  1881.     PutLine3(LINES-1,0, catgets(elm_msg_cat, AliasesSet, AliasesAddressAs,
  1882.             "Messages addressed as: %s (%s)"), address, buffer);
  1883.     if (strlen(comment) != 0) {
  1884.         strcat(buffer, ", ");
  1885.         strcat(buffer, comment);
  1886.     }
  1887.  
  1888.     PutLine3(LINES-2,0, catgets(elm_msg_cat, AliasesSet, AliasesAddressTo,
  1889.             "New alias: %s is '%s'."), aliasname, buffer);
  1890.     CleartoEOLN();
  1891. /*
  1892.  *    Kludge Alert:  Spaces are padded to the front of the prompt
  1893.  *    to write over the previous question.  Should probably record
  1894.  *    the end of the line, move to it, and CleartoEOLN() it.
  1895.  */
  1896.     MCsprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesAcceptNew,
  1897.         "      Accept new alias? (%c/%c) "), *def_ans_yes, *def_ans_no);
  1898.     if((ch = want_to(buffer, *def_ans_yes, LINES-3, 0)) == *def_ans_yes) {
  1899.         if (replace) {
  1900.             old_alias[0] = aliases[replacement]->alias;
  1901.         /*
  1902.          *  First, clear flag if this is marked to be deleted.
  1903.          *  This prevents the problem where they marked it for
  1904.          *  deletion and then figured out that it could be
  1905.          *  c)hanged but didn't explicitly U)ndelete it.  Without
  1906.          *  this test, the resync action would then delete
  1907.          *  the new alias we just so carefully added to the
  1908.          *  text file.
  1909.          */
  1910.             if (ison(aliases[replacement]->status, DELETED)) {
  1911.                 clearit(aliases[replacement]->status, DELETED);
  1912.             }
  1913.         /*
  1914.          *  Changed aliases are given the NEW flag.
  1915.          */
  1916.             setit(aliases[replacement]->status, NEW);
  1917.             show_msg_status(replacement);
  1918.         /*
  1919.          *  Now we can delete it...
  1920.          */
  1921.             delete_from_alias_text(old_alias, 1);
  1922.         /*
  1923.          *  Kludge Alert:  We need to get the trailing comma
  1924.          *  (added in delete_from_alias_text()) off of the
  1925.          *  alias since the display won't be re-sync'd right
  1926.          *  away.
  1927.          */
  1928.             *((old_alias[0])+strlen(old_alias[0])-1) = '\0';
  1929.         }
  1930.         add_to_alias_text(aliasname, firstname, lastname, comment, address);
  1931.     }
  1932.     ClearLine(LINES-2);
  1933.     ClearLine(LINES-1);
  1934.     return(ch == *def_ans_yes ? 1 : 0);
  1935.  
  1936. }
  1937.